package com.hyjiacan.h2c

import java.sql.*

class H2(val url: String, val user: String, val pswd: String) {
    init {
        Class.forName("org.h2.Driver")
    }

    private lateinit var connection: Connection

    fun open() {
        connection = DriverManager.getConnection(
            "jdbc:h2:${url};DB_CLOSE_ON_EXIT=TRUE", user, pswd,
        )
        connection.autoCommit = true
    }

    fun close() {
        connection.close()
    }

    fun execute(sql: String): ExecuteResult {
        val result = ExecuteResult()
        connection.createStatement(ResultSet.TYPE_SCROLL_INSENSITIVE, ResultSet.CONCUR_READ_ONLY).use { statement ->
            try {
                val isQuery = statement.execute(sql)
                if (isQuery) {
                    fillResult(statement.resultSet, result)
                    result.rowsAffected = result.data!!.size
                } else {
                    result.rowsAffected = statement.updateCount
                }
                result.success = true
            } catch (e: Exception) {
                result.message = e.message
            }
        }
        return result
    }

    private fun fillResult(resultSet: ResultSet, result: ExecuteResult) {
        resultSet.absolute(-1)
        val rowsAffected = resultSet.row
        resultSet.absolute(0)

        result.rowsAffected = rowsAffected

        val meta = resultSet.metaData
        val columns = mutableListOf<String>()
        for (i in 0 until meta.columnCount) {
            columns.add(meta.getColumnLabel(i + 1))
        }
        result.columns = columns.toTypedArray()
        val data = Array(rowsAffected) {
            return@Array Array<Any?>(columns.size) inner@{
                return@inner null
            }
        }
        var rowIndex = 0
        while (resultSet.next()) {
            var colIndex = 0
            columns.forEach {
                data[rowIndex][colIndex] = resultSet.getObject(it)
                colIndex++
            }
            rowIndex++
        }
        result.data = data
    }
}